﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TracyGUI.UIData;
using Tracy.DataModel;
using System.ComponentModel;
using Tracy;
using Tracy.Messages;
using Tracy.Handlers;
using SharedLib.BasicServices.MessageFramework;
using System.IO;
using SharedLib.Helpers;

namespace TracyGUI
{
    public partial class FormMain
    {
        private Dictionary<string, ListBoxItemEntry> _mappingEntry = new Dictionary<string, ListBoxItemEntry>();

        bool _isUpdatingEntry = false;
        private void listBoxEntries_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_isUpdatingEntry)
            {
                ClearResourceListView();
                ClearMediaFileListView();
                if (listBoxEntries.SelectedItem != null)
                {
                    //TODO: Improve performance
                    ListBoxItemEntry selectedEntry = listBoxEntries.SelectedItem as ListBoxItemEntry;
                    AddResourcesToUI(TracyBus.Instance.ResourceProvider.GetItemByEntry(selectedEntry.Data));
                    AddMediaFilesToUI(TracyBus.Instance.MediaFileProvider.GetItemByEntry(selectedEntry.Data));
                }
                else
                {
                    AddResourcesToUI(TracyBus.Instance.ResourceProvider.GetItems());
                    AddMediaFilesToUI(TracyBus.Instance.MediaFileProvider.GetItems());
                }
            }

        }



        private void LoadEntries()
        {
            foreach (Entry entry in TracyBus.Instance.EntryProvider.GetItems())
            {
                AddEntry(entry);
                
            }
        }

        private void ShowFormEntry(FormEntry.EntryEditMode mode)
        {
            //TODO: Refactor this logic
            FormEntry formEntry;
            ListBoxItemEntry selectedEntryItem = listBoxEntries.SelectedItem as ListBoxItemEntry;
            string previousPath = null;
            if (selectedEntryItem != null && mode == FormEntry.EntryEditMode.Modify)
            {
                if (selectedEntryItem.Data != null)
                {
                    previousPath = selectedEntryItem.Data.SavePath;
                }
                formEntry = new FormEntry(mode, selectedEntryItem.Data);
            }
            else
            {
                formEntry = new FormEntry(mode, null);
            }
            if (formEntry.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {

                if (mode == FormEntry.EntryEditMode.Modify)
                {
                    TracyBus.Instance.EntryProvider.UpdateItem(formEntry.EditingEntry);
                    TracyBus.Instance.FilterProvider.SetFilterSets(formEntry.SelectedFilterSets, formEntry.EditingEntry);
                    UpdateEntry(formEntry.EditingEntry);

                    if (previousPath != null && previousPath != formEntry.EditingEntry.SavePath)
                    {
                        //SavePath Changed
                        if (MessageBox.Show("Save path changed, would you like to move the files to the new location?", "Changing save path", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                        {
                            MoveMediaFiles(formEntry.EditingEntry, previousPath);
                        }
                    }
                }
                else
                {
                    TracyBus.Instance.EntryProvider.AddItem(formEntry.EditingEntry);
                    TracyBus.Instance.FilterProvider.SetFilterSets(formEntry.SelectedFilterSets, formEntry.EditingEntry);
                    AddEntry(formEntry.EditingEntry);
                }

                //Trigger Scan for this entry
                TaskMessage taskMsg = new TaskMessage(this, typeof(FeedScanHandler), formEntry.EditingEntry, null);
                TracyBus.Instance.MessageDispatcher.EnqueueMessage(taskMsg);
                //TODO: Work out a efficient way to sync UI and db
                
            }
        }
        
        private void MoveMediaFiles(Entry entry, string previousPath)
        {
            if (entry != null && !String.IsNullOrEmpty(previousPath))
            {
                lock (_lockHelperFileMove)
                {
                    foreach (MediaFile file in TracyBus.Instance.MediaFileProvider.GetItemByEntry(entry))
                    {
                        if (file.Status == "Watched" || file.Status == "Ready")
                        {
                            file.Properties[MediaFile.KEY_PREVIOUS_STATUS] = file.Status;
                            file.Status = "Moving";
                            file.Properties[MediaFile.KEY_PREVIOUS_PATH] = previousPath;
                            TracyBus.Instance.MediaFileProvider.UpdateItem(file);
                            TracyBus.Instance.MessageDispatcher.EnqueueMessage(new TaskMessage(this, typeof(FileMonitorHandler), file, null));

                            if (filesInPath.ContainsKey(previousPath)) filesInPath[previousPath]++;
                            else filesInPath[previousPath] = 1;
                        }
                    }
                }
            }
            //TODO:Remove folder and handle exception
        }

        private object _lockHelperFileMove = new object();
        private Dictionary<string, int> filesInPath = new Dictionary<string,int>();

        //Delete original folder, triggered by OnFileUpdated
        private void FileMoved(MediaFile copiedFile)
        {
            if (copiedFile != null)
            {
                if (copiedFile.Properties.ContainsKey(MediaFile.KEY_PREVIOUS_PATH))
                {
                    lock (_lockHelperFileMove)
                    {
                        string previousPath = copiedFile.Properties[MediaFile.KEY_PREVIOUS_PATH];
                        copiedFile.Properties.Remove(MediaFile.KEY_PREVIOUS_PATH);
                        TracyBus.Instance.MediaFileProvider.UpdateItem(copiedFile);

                        if (filesInPath.ContainsKey(previousPath))
                        {
                            filesInPath[previousPath]--;
                            if (filesInPath[previousPath] <= 0)
                            {
                                filesInPath.Remove(previousPath);
                                //Remove Folder
                                IOHelper.DeleteFolderIfNotEmpty(previousPath);
                            }
                        }
                    }
                    
                }
            }
        }

        private void UpdateEntry(Entry entry)
        {
            if (_mappingEntry.ContainsKey(entry.ID))
            {
                _isUpdatingEntry = true;
                int previousSelectedIndex = listBoxEntries.SelectedIndex;
                int oldIndex = listBoxEntries.Items.IndexOf(_mappingEntry[entry.ID]);
                listBoxEntries.Items.RemoveAt(oldIndex);
                _mappingEntry.Remove(entry.ID);
                AddEntry(entry, oldIndex);
                listBoxEntries.SelectedIndex = previousSelectedIndex;
                _isUpdatingEntry = false;
            }
        }

        private void AddEntry(Entry entry, int index = 0)
        {
            ListBoxItemEntry item = new ListBoxItemEntry(entry);
            listBoxEntries.Items.Insert(index, item);
            _mappingEntry.Add(entry.ID, item);
        }
        
        private void toolStripButtonAddEntry_Click(object sender, EventArgs e)
        {
            ShowFormEntry(FormEntry.EntryEditMode.Create);
        }

        private void toolStripMenuItemAddEntry_Click(object sender, EventArgs e)
        {
            ShowFormEntry(FormEntry.EntryEditMode.Create);
        }

        private void contextMenuStripEntry_Opening(object sender, CancelEventArgs e)
        {
            if (listBoxEntries.SelectedIndex == -1)
            {
                toolStripMenuItemModifyEntry.Enabled = false;
                toolStripMenuItemRemoveEntry.Enabled = false;
            }
            else
            {
                toolStripMenuItemModifyEntry.Enabled = true;
                toolStripMenuItemRemoveEntry.Enabled = true;
            }
        }

        private void listBoxEntries_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            ShowFormEntry(FormEntry.EntryEditMode.Modify);
        }

        private void toolStripMenuItemModifyEntry_Click(object sender, EventArgs e)
        {
            ShowFormEntry(FormEntry.EntryEditMode.Modify);
        }
        private void listBoxEntries_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)//Select item on right click
            {
                int selectedIndex = listBoxEntries.IndexFromPoint(e.X, e.Y);
                if (selectedIndex != -1)
                {
                    listBoxEntries.SelectedIndex = selectedIndex;
                }
            }
        }
        private void toolStripMenuItemRemoveEntry_Click(object sender, EventArgs e)
        {
            if (listBoxEntries.SelectedIndex != -1)
            {
                ListBoxItemEntry item = listBoxEntries.SelectedItem as ListBoxItemEntry;
                if (item != null && item.Data != null && item.Data is Entry)
                {
                    Entry entry = item.Data as Entry;
                    listBoxEntries.Items.Remove(item);
                    listBoxEntries.SelectedIndex = -1;
                    RemoveEntry(entry);
                }
            }
        }

        private void RemoveEntry(Entry entry)
        {
            _mappingEntry.Remove(entry.ID);
            List<Resource> resourcesToRemove = TracyBus.Instance.ResourceProvider.GetItemByEntry(entry);
            RemoveResources(resourcesToRemove);
            TracyBus.Instance.EntryProvider.RemoveItem(entry.ID);
            IOHelper.DeleteFolderIfNotEmpty(entry.SavePath);
        }
    }
}
